#include <netdb.h>

#include "comm.h"


void host_info(const char *host);
void host_addr(const char *host);
void get_addr_info(const char *host, const char *service);
void get_service(void);
int main(int ac , char *av[]){
    int i;
    char **pptr;
    for(pptr=++av; *pptr; ++pptr){

        host_info(*pptr);
        host_addr(*pptr);
        get_addr_info(*pptr, NULL);
    }
    get_service();
    return 0;
}

/*
 * host something like: iori  www.baidu.com 
 * 127.0.0.1 etc won't get hostname
 */
void host_info(const char *host){
    struct hostent *hptr;
    char *ptr, **pptr;
    char addr[MAXLINE];
    printf("host info of :%s\n", host);
    if((hptr=gethostbyname(host))==NULL){
        hstrerror(h_errno);
        return;
    }
    printf("official name: %s\n", hptr->h_name);
    for(pptr=hptr->h_aliases; *pptr!=NULL; ++pptr){
        printf("\tAlias: %s\n", *pptr);
    }
    for(pptr=hptr->h_addr_list; *pptr!=NULL; ++pptr){
        printf("\tAddress: %s\n", inet_ntop(hptr->h_addrtype, *pptr, addr, sizeof(addr)));
    }
}

void host_addr(const char *remote){
    struct hostent *hptr;
    char *ptr, **pptr;
    char addr[MAXLINE];
    struct in_addr ina;
    inet_pton(AF_INET, remote, &ina);
    printf("addr info of :%s\n", remote);
    if((hptr=gethostbyaddr(&ina, sizeof(ina), AF_INET))==NULL){
        hstrerror(h_errno);
        return;
    }
    printf("official name: %s\n", hptr->h_name);
    for(pptr=hptr->h_aliases; *pptr!=NULL; ++pptr){
        printf("\tAlias: %s\n", *pptr);
    }
    for(pptr=hptr->h_addr_list; *pptr!=NULL; ++pptr){
        printf("\tAddress: %s\n", inet_ntop(hptr->h_addrtype, *pptr, addr, sizeof(addr)));
    }
}

void get_addr_info(const char *host, const char *service){
    struct addrinfo hints;
    struct addrinfo *res, *it;
    struct sockaddr_in *inp;
    char saddr[MAXLINE];
    int ai_err;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_CANONNAME; /* to query canonname, otherwise canonname nulll */
    hints.ai_protocol = 0;
    printf("get addr info: %s\n", host);
    if((ai_err=getaddrinfo(host, service, &hints, &res))!=0){
        fprintf(stderr, "getaddrinfo : %s\n", gai_strerror(ai_err));
        return;
    }
    for(it=res; it; it=it->ai_next){
        printf("hostname: %s\n", it->ai_canonname);
        inp = (struct sockaddr_in*)it->ai_addr;
        printf("address: %s\n", inet_ntop(inp->sin_family, &inp->sin_addr, saddr, sizeof(saddr)));
    }
}

void get_service(void){

    struct servent *serv;
    char **aliases;
    char * services[]={"ftp", "http", "https", "tftp", "dns", "smtp", "pop3"};
    int ports[] = {22, 21, 80, 443, 53, 8080, };
    int i;
    for(i=0; i<sizeof(services)/sizeof(services[0]); ++i){
        if((serv=getservbyname(services[i], NULL))){
            printf("service %s info\n", services[i]);
            /* serv->s_port int but we should use noths, as port as short type */
            printf("official name: %s, port %d\n", serv->s_name, ntohs(serv->s_port));
            for(aliases=serv->s_aliases; *aliases; ++aliases){
                printf("aliase: %s\n", *aliases);
            }
        }
    }
    for(i=0; i<sizeof(ports)/sizeof(ports[0]); ++i){
        /* getservbyport accept int port with network order, we should use htons not htonl */
        if((serv=getservbyport(htons(ports[i]), NULL))){
            printf("port %d info\n", ports[i]);
            printf("official name: %s, port %d\n", serv->s_name, ntohs(serv->s_port));
            for(aliases=serv->s_aliases; *aliases; ++aliases){
                printf("aliase: %s\n", *aliases);
            }
        }else{
            fprintf(stderr, "get port %d service fail\n", ports[i]);
        }
    }
}
